import { cloneDeep } from 'lodash';
const { pathToRegexp } = require('path-to-regexp');
import moment from 'moment';
import 'moment/locale/zh-cn';
import store from 'store';
import { i18n } from './config';

export classnames from 'classnames';
export config from './config';
// export request from './request';
export { Color } from './theme';

export const languages = i18n ? i18n.languages.map(item => item.key) : [];
export const defaultLanguage = i18n ? i18n.defaultLanguage : '';

/**
 * Query objects that specify keys and values in an array where all values are objects.
 * @param   {array}         array   An array where all values are objects, like [{key:1},{key:2}].
 * @param   {string}        key     The key of the object that needs to be queried.
 * @param   {string}        value   The value of the object that needs to be queried.
 * @return  {object|undefined}   Return frist object when query success.
 */
export function queryArray(array, key, value) {
    if (!Array.isArray(array)) {
        return;
    }
    return array.find(_ => _[key] === value);
}

/**
 * Convert an array to a tree-structured array.
 * @param   {array}     array     The Array need to Converted.
 * @param   {string}    id        The alias of the unique ID of the object in the array.
 * @param   {string}    parentId       The alias of the parent ID of the object in the array.
 * @param   {string}    children  The alias of children of the object in the array.
 * @return  {array}    Return a tree-structured array.
 */
export function arrayToTree(array, id = 'id', parentId = 'pid', children = 'children') {
    const result = [];
    const hash = {};
    const data = cloneDeep(array);

    data.forEach((item, index) => {
        hash[data[index][id]] = data[index];
    });

    data.forEach(item => {
        const hashParent = hash[item[parentId]];
        if (hashParent) {
            !hashParent[children] && (hashParent[children] = []);
            hashParent[children].push(item);
        } else {
            result.push(item);
        }
    });
    return result;
}

/**
 * In an array object, traverse all parent IDs based on the value of an object.
 * @param   {array}     array     The Array need to Converted.
 * @param   {string}    current   Specify the value of the object that needs to be queried.
 * @param   {string}    parentId  The alias of the parent ID of the object in the array.
 * @param   {string}    id        The alias of the unique ID of the object in the array.
 * @return  {array}    Return a key array.
 */
export function queryPathKeys(array, current, parentId, id = 'id') {
    const result = [current];
    const hashMap = new Map();
    array.forEach(item => hashMap.set(item[id], item));

    const getPath = current => {
        const currentParentId = hashMap.get(current)[parentId];
        if (currentParentId) {
            result.push(currentParentId);
            getPath(currentParentId);
        }
    };

    getPath(current);
    return result;
}

/**
 * In an array of objects, specify an object that traverses the objects whose parent ID matches.
 * @param   {array}     array     The Array need to Converted.
 * @param   {string}    current   Specify the object that needs to be queried.
 * @param   {string}    parentId  The alias of the parent ID of the object in the array.
 * @param   {string}    id        The alias of the unique ID of the object in the array.
 * @return  {array}    Return a key array.
 */
export function queryAncestors(array, current, parentId, id = 'id') {
    const result = [current];
    const hashMap = new Map();
    array.forEach(item => hashMap.set(item[id], item));

    const getPath = current => {
        const currentParentId = hashMap.get(current[id])[parentId];
        if (currentParentId) {
            result.push(hashMap.get(currentParentId));
            getPath(hashMap.get(currentParentId));
        }
    };

    getPath(current);
    return result;
}

/**
 * Query which layout should be used for the current path based on the configuration.
 * @param   {layouts}     layouts   Layout configuration.
 * @param   {pathname}    pathname  Path name to be queried.
 * @return  {string}   Return frist object when query success.
 */
export function queryLayout(layouts, pathname) {
    let result = 'public';

    const isMatch = regepx => {
        return regepx instanceof RegExp
            ? regepx.test(pathname)
            : pathToRegexp(regepx).exec(pathname);
    };

    for (const item of layouts) {
        let include = false;
        let exclude = false;
        if (item.include) {
            for (const regepx of item.include) {
                if (isMatch(regepx)) {
                    include = true;
                    break;
                }
            }
        }

        if (include && item.exclude) {
            for (const regepx of item.exclude) {
                if (isMatch(regepx)) {
                    exclude = true;
                    break;
                }
            }
        }

        if (include && !exclude) {
            result = item.name;
            break;
        }
    }

    return result;
}

export function getLocale() {
    return store.get('locale') || defaultLanguage;
}

export function setLocale(language) {
    if (getLocale() !== language) {
        moment.locale(language === 'zh' ? 'zh-cn' : language);
        store.set('locale', language);
        window.location.reload();
    }
}
